// 自主实现一个any通用类型容器
// 思路1：使用模板，不行，需要指定类型
// 思路2：使用内部类，不行，在使用的时候内部只能存储一个类型，无法做到运行时变换类型
// 思路3：在内部使用多态的性质，子类对象可以指向父类指针，可以实现运行时变换存储类型
#include <iostream>
#include <memory>
#include <typeinfo>
#include <cassert>
#include <string>
#include <unistd.h>
#include <any>

class Any
{
private:
    class holder
    {
    public:
        virtual ~holder() {}
        virtual holder* clone() = 0;
        virtual const std::type_info& getType() = 0;
    };

    template<typename T>
    class placeHolder: public holder
    {
    public:
        T _val;
    public:
        placeHolder() = default;
        placeHolder(const T& val) :_val(val) {}
        ~placeHolder() override {}
        const std::type_info& getType() override { return typeid(T); }
        holder* clone() override{
            return new placeHolder<T>(_val);
        }       
    };
private:
    holder* _pData;
public:
    Any() :_pData(nullptr) {}
    ~Any() { delete _pData; }
    // 通用类型构造
    template<typename T>
    Any(const T& val){
        _pData = (new placeHolder<T>(val));
    }
    // 拷贝构造: 需要注意空any的情况
    Any(const Any& other) :_pData(other._pData ? other._pData->clone() : nullptr) {}
    
    void swap(Any& other){
        std::swap(_pData, other._pData);
    }
    // 赋值运算符重载
    const Any& operator=(Any other){
        // Any newAny(other);
        swap(other);
        return *this;
    }
    // 获取数据
    template<typename T>
    T* get(){
        assert(typeid(T) == _pData->getType());
        return &(static_cast<placeHolder<T>*>(_pData)->_val); 
    }  
    
};

class test
{
public:
    test() { printf("构造!\n"); }
    test(const test& t) { printf("拷贝\n"); }
    ~test() { printf("析构!\n"); }
};

int main()
{
    // Any a;
    std::any a;
    test t;
    {
        Any a(t);
    }

    // a = 10;
    // printf("%d\n", *(a.get<int>()));
    // printf("%lf\n", *(a.get<double>()));
    // a = 1.1;
    // a = test();
    while(1) sleep(1);
    return 0;
}